//
//  NSObject+JSONExtension.m
//  runtimeTest
//
//  Created by Song on 2018/4/18.
//  Copyright © 2018年 Song. All rights reserved.
//

#import "NSObject+JSONExtension.h"
#import <objc/runtime.h>

@implementation NSObject (JSONExtension)

-(void)setDict:(NSDictionary *)dict {
    
    Class c = self.class;
    
    while (c && c!=[NSObject class]) {
        unsigned int outCount = 0;
        Ivar *ivars = class_copyIvarList(c , &outCount);
        
        for (int i = 0; i < outCount; i++) {
            Ivar ivar = ivars[i];

            NSString *key = [NSString stringWithUTF8String:ivar_getName(ivar)];
//            NSLog(@"ivar_getName = %@",key);
            
            key = [key substringFromIndex:1]; // 成员变量名转换为属性名 (截字符串，去掉下划线)
            id value = dict[key]; // 取出字典的值
            
            if (value == nil) { // 如果模型属性数量大于字典键值对数量，模型属性会被赋值为 nil 而报错
                continue;
            }
            
            // 获得成员变量的类型
            NSString *type = [NSString stringWithUTF8String:ivar_getTypeEncoding(ivar)];
            NSLog(@"ivar_getName = %@, %@",key,type);
            
            // 如果属性是对象类型
            NSRange range = [type rangeOfString:@"@"];
            if (range.location != NSNotFound) {
                // 截取（@"Dog" 截取为 Dog）
                type = [type substringWithRange:NSMakeRange(2, type.length-3)];
                // 排除系统的对象类型
                if (![type hasPrefix:@"NS"]) {
                    // 将对象名，转换为对象的类型  将新的对象字典转模型（递归）
                    Class class = NSClassFromString(type);
                    value = [class GGGGGGGobjectWithDict:value];
                    
                    
                }else if ([type isEqualToString:@"NSArray"]) {
                    
                    // 如果是数组类型，将数组中的每个模型进行字典转模型，先创建一个临时数组存放模型
                    NSArray *array11 = (NSArray *)value;
                    NSLog(@"array11 = %@",array11);
                    NSMutableArray *mArray = [NSMutableArray array];
                    
                    // 获取到每个模型的类型
                    id class1;
                    if ([self respondsToSelector:@selector(arrayObjectClass)]) {// 如果arrayObjectClass方法实现了，就调用
                        NSString *classStr = [self arrayObjectClass];
                        NSLog(@"classStr = %@",classStr);
                        class1 = NSClassFromString(classStr);
                    }else {
                        NSLog(@"数组内模型是未知类型");
                        return;
                    }
                    // 将数组中的所有的模型 进行字典转模型
                    for (int i = 0; i < array11.count; i++) {
                        [mArray addObject:[class1 GGGGGGGobjectWithDict:value[i]]];
                    }
                    value = mArray;
                    
                }
                
                
            }
            
            // 将字典中的值设置到模型上
            [self setValue:value forKey:key];
        }
        free(ivars);
        c = [c superclass]; // 获取父类的属性  (?)
    }
}

+ (instancetype )GGGGGGGobjectWithDict:(NSDictionary *)dict {
    NSObject *obj = [[self alloc]init];
    [obj setDict:dict];
    return obj; 
}

// 返回数组中都是什么类型的模型对象
- (NSString *)arrayObjectClass {
    return @"Book";
}

@end
